package org.loong.crypto.service.core.provider.impl;

import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;

import javax.crypto.SecretKey;

import org.loong.crypto.common.exception.InvalidKeyException;
import org.loong.crypto.core.algorithm.CipherAlgorithm;
import org.loong.crypto.core.algorithm.EncryptionMethod;

/**
 * The base abstract class for DESede encrypter and decrypter.
 * 
 * <p>
 * Supports the following algorithms:
 *
 * <ul>
 *     <li>{@link org.loong.crypto.core.algorithm.CipherAlgorithm#DES}
 * </ul>
 * 
 * <p>
 * Supports the following encrypt methods:
 *
 * <ul>
 *     <li>{@link org.loong.crypto.core.algorithm.EncryptionMethod#DESEDE_ECB}
 *     <li>{@link org.loong.crypto.core.algorithm.EncryptionMethod#DESEDE_ECB_PKCS5}
 *     <li>{@link org.loong.crypto.core.algorithm.EncryptionMethod#DESEDE_ECB_PKCS7}
 *     <li>{@link org.loong.crypto.core.algorithm.EncryptionMethod#DESEDE_CBC}
 *     <li>{@link org.loong.crypto.core.algorithm.EncryptionMethod#DESEDE_CBC_PKCS5}
 *     <li>{@link org.loong.crypto.core.algorithm.EncryptionMethod#DESEDE_CBC_PKCS7}
 * </ul>
 */
public abstract class DESedeCipherProvider extends BaseCipherProvider {

    /**
     * The supported encryption algorithms by the DESede cipher provider class.
     */
    public static final Set<CipherAlgorithm> SUPPORTED_ALGORITHMS;

    /**
     * The supported encryption methods by the DESede cipher provider class.
     */
    public static final Set<EncryptionMethod> SUPPORTED_ENCRYPTION_METHODS;

    static {
        Set<CipherAlgorithm> algs = new LinkedHashSet<>();
        algs.add(CipherAlgorithm.DESEDE);
        SUPPORTED_ALGORITHMS = Collections.unmodifiableSet(algs);

        Set<EncryptionMethod> encs = new LinkedHashSet<>();
        encs.add(EncryptionMethod.DESEDE_ECB);
        encs.add(EncryptionMethod.DESEDE_ECB_PKCS5);
        encs.add(EncryptionMethod.DESEDE_ECB_PKCS7);
        encs.add(EncryptionMethod.DESEDE_CBC);
        encs.add(EncryptionMethod.DESEDE_CBC_PKCS5);
        encs.add(EncryptionMethod.DESEDE_CBC_PKCS7);
        SUPPORTED_ENCRYPTION_METHODS = Collections.unmodifiableSet(encs);
    }

    /**
     * The Key Encryption Key (KEK).
     */
    private final SecretKey secretKey;

    /**
     * Creates a new DESede provider.
     * 
     * @param secretKey the secretKey
     */
    protected DESedeCipherProvider(final SecretKey secretKey) {
        super(SUPPORTED_ALGORITHMS, SUPPORTED_ENCRYPTION_METHODS);

        if (secretKey == null) {
            throw new InvalidKeyException("The Secret key must not be null");
        }
        
        this.secretKey = secretKey;
    }

    /**
     * Gets the Key Encryption Key.
     *
     * @return the Key Encryption Key.
     */
    public SecretKey getSecretKey() {
        return secretKey;
    }
}
